package vip.xiaomoli.courier.component.timewheel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vip.xiaomoli.courier.util.CourierUtil;

import java.util.Iterator;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadPoolExecutor;

public class TaskSlotLoader extends TimerTask {

	private static final Logger LOG = LoggerFactory.getLogger(TaskSlotLoader.class);
	
	private TaskSlotWheel slotWheel;

	private ThreadPoolExecutor slotThreadPool;

	private ThreadPoolExecutor taskThreadPool;

	TaskSlotLoader(TaskSlotWheel slotWheel, ThreadPoolExecutor slotThreadPool, ThreadPoolExecutor taskThreadPool) {
		super();
		this.slotWheel = slotWheel;
		this.slotThreadPool = slotThreadPool;
		this.taskThreadPool = taskThreadPool;
	}

	@Override
	public void run() {
		if (slotWheel == null) return;
		try {
			int currentSecond = CourierUtil.getCurrentSecondInHour();
			TaskSlot taskSlot = slotWheel.pick(currentSecond);
			LOG.debug("Current Slot: " + currentSecond);
			slotThreadPool.execute(new TaskScanner(taskSlot.getTasks(), currentSecond)); // 把一个槽位的任务加载到扫描器
		} catch (Exception e) {
			LOG.error(e.getMessage(), e); // 忽略异常，继续执行
		}
	}

    final class TaskScanner implements Runnable {
    	ConcurrentLinkedQueue<CourierTask> tasks;
    	int slotIndex;

		TaskScanner(ConcurrentLinkedQueue<CourierTask> tasks, int slotIndex) {
			super();
			this.tasks = tasks;
			this.slotIndex = slotIndex;
		}

		@Override
		public void run() {
			if (tasks == null || tasks.size() == 0) return;

			Iterator<CourierTask> it = tasks.iterator();
            while (it.hasNext()) {
            	CourierTask task = it.next();
                if (task.getCycleNum() <= 0) {
					LOG.debug("Task execute: currentSlot={}, task={}", slotIndex, task.toString());
                    taskThreadPool.execute(task);
                    it.remove();
                } else {
					LOG.debug("Task cycleNum countDown: currentSlot={}, task={}", slotIndex, task.toString());
                    task.countDown();
                }
            }
		}
	}

}
